package ${filePackageName};

import ${annotationPackage}.QueryProperty;
import org.springframework.data.annotation.Id;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;

import java.lang.reflect.Field;
import java.util.regex.Pattern;

/**
 * Mongo分页排序参数
 *
 * @author ${projectAuthor}
 * @version 1.0
 * @date ${nowDate}
 */
@ApiModel(value = "查询条件",description="查询条件")
public class MongoParam<T> {

    /**
     * 对象
     */
    @ApiModelProperty(value = "对象")
    private T obj;

    /**
     * 第几页
     */
    @ApiModelProperty(value = "分页参数 第几页",example = "1")
    private Integer pageIndex;

    /**
     * 每页多少条记录
     */
    @ApiModelProperty(value = "分页参数 每页条数",example = "10")
    private Integer pageSize;

    /**
     * 排序名称 对应数据库字段名
     */
    @ApiModelProperty(value="排序名,对应数据库字段名")
    private String sortName;

    /**
     * 排序顺序 asc
     */
    public static final String ORDER_ASC = "asc";

    /**
     * 排序顺序 desc
     */
    public static final String ORDER_DESC = "desc";

    /**
     * 排序顺序 desc 或asc
     */
    @ApiModelProperty(value="排序顺序 desc或asc")
    private String sortOrder;

    public MongoParam(Integer pageIndex, Integer pageSize, String sortName, String sortOrder, T obj) {
        this.obj = obj;
        this.pageIndex = pageIndex;
        this.pageSize = pageSize;
        this.sortName = sortName;
        this.sortOrder = sortOrder;
    }

    public MongoParam() {
    }

    public MongoParam(Integer pageIndex, Integer pageSize, String sortName, String sortOrder) {
        this.pageIndex = pageIndex;
        this.pageSize = pageSize;
        this.sortName = sortName;
        this.sortOrder = sortOrder;
    }

    public MongoParam(Integer pageIndex, Integer pageSize) {
        this.pageIndex = pageIndex;
        this.pageSize = pageSize;
    }

    public MongoParam(String sortName, String sortOrder) {
        this.sortName = sortName;
        this.sortOrder = sortOrder;
    }

    /**
     * 获取排序顺序
     * @return Sort.Direction对象
     */
    public Sort.Direction getSortDirection(){
        if(ORDER_DESC.equals(sortOrder)){
            return Sort.Direction.DESC;
        }else{
            return Sort.Direction.ASC;
        }
    }

    /**
     * 获取query
     * @return Query对象
     */
    public Query getQuery(){
        Query query = new Query();
        if(pageIndex!=null && pageSize!=null){
            query.skip((pageIndex-1)*pageSize);
            query.limit(pageSize);
        }
        if(sortName!=null && !"".equals(sortName)){
            Sort sort = Sort.by(this.getSortDirection(), sortName);
            query.with(sort);
        }
        Criteria criteria = parseObjToCriteria(obj);
        if(criteria!=null){
            query.addCriteria(criteria);
        }
        return query;
    }

    /**
     * 获取query
     * @param obj 对象
     * @param <T> 对象类型
     * @return Query对象
     */
    public static <T> Query getQuery(T obj){
        Query query = new Query();
        Criteria criteria = parseObjToCriteria(obj);
        if(criteria!=null){
            query.addCriteria(criteria);
        }
        return query;
    }

    /**
     * obj转Criteria
     * @param obj 对象
     * @param <T> 对象类型
     * @return Criteria对象
     */
    public static <T> Criteria parseObjToCriteria(T obj){
        Criteria fieldCond = null;
        if(obj==null){
            return fieldCond;
        }
        try {
            Field[] fields = obj.getClass().getDeclaredFields();
            for (Field field:fields){
                field.setAccessible(true);
                String fieldName = field.getName();
                Object value = field.get(obj);
                if(value!=null && !"".equals(String.valueOf(value))){
                    QueryProperty queryProperty = field.getAnnotation(QueryProperty.class);
                    if(queryProperty!=null){
                        fieldName = queryProperty.isAuto()==true?field.getName():queryProperty.name();
                        if(queryProperty.isLike()==true){
                            Pattern pattern=Pattern.compile("^.*"+value+".*$", Pattern.CASE_INSENSITIVE);
                            fieldCond = fieldCond ==null? Criteria.where(fieldName).regex(pattern):fieldCond.and(fieldName).regex(pattern);
                        }else{
                            fieldCond = fieldCond ==null?Criteria.where(fieldName).is(value):fieldCond.and(fieldName).is(value);
                        }
                    }
                }
            }
        }catch (IllegalAccessException e){
            e.printStackTrace();
        }
        return fieldCond;
    }

    /**
     * obj转Update
     * @param obj 对象
     * @param <T> 对象类型
     * @return Update对象
     */
    public static <T> Update parseObjToUpdate(T obj){
        Update update = new Update();
        if(obj==null){
            return null;
        }
        try {
            Field[] fields = obj.getClass().getDeclaredFields();
            for (Field field:fields){
                field.setAccessible(true);
                String fieldName = field.getName();
                Object value = field.get(obj);
                if(value!=null && !"".equals(String.valueOf(value))){
                    QueryProperty queryProperty = field.getAnnotation(QueryProperty.class);
                    Id anoId = field.getAnnotation(Id.class);
                    if(queryProperty!=null && anoId==null){
                        fieldName = queryProperty.isAuto()==true?field.getName():queryProperty.name();
                        update.set(fieldName,value);
                        continue;
                    }
                }
            }
        }catch (IllegalAccessException e){
            e.printStackTrace();
        }
        return update;
    }

    /**
     * obj转Criteria
     * @param obj 对象
     * @param <T> 对象类型
     * @return Criteria对象
     */
    public static <T> Criteria getPrimaryCriteria(T obj){
        Criteria criteria = null;
        if(obj==null){
            return null;
        }
        try {
            Field[] fields = obj.getClass().getDeclaredFields();
            for (Field field:fields){
                field.setAccessible(true);
                String fieldName = field.getName();
                Object value = field.get(obj);
                if(value!=null && !"".equals(String.valueOf(value))){
                    Id anoId = field.getAnnotation(Id.class);
                    if(anoId!=null){
                        criteria = Criteria.where(fieldName).is(value);
                        break;
                    }
                }
            }
        }catch (IllegalAccessException e){
            e.printStackTrace();
        }
        return criteria;
    }
}
